package com.sky.aspect;


import com.sky.anno.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

//aop公共字段填充切面类
@Slf4j
@Aspect
@Component
public class AutoFillAspect {
    @Before("@annotation(com.sky.anno.AutoFill)")
    public void autoFill(JoinPoint joinPoint) {
        //1.获取目标方法上的注解，并拿到注解里属性值
        MethodSignature  methodSignature = (MethodSignature) joinPoint.getSignature();//获取方法签名
        Method method = methodSignature.getMethod();//获取方法对象
        AutoFill annotation = method.getAnnotation(AutoFill.class);//获取注解对象
        OperationType operationType = annotation.value();//获取注解属性值
        //2获取到目标方法的参数对象
        Object[] args = joinPoint.getArgs();//获取参数
        if (args == null || args.length == 0){
            return;
        }
        Object object = args[0];//获取第一个参数对象如 void insert(Employee employee)中的Employee employee就是,这里也只有一个参数
        //3、判断注解中属性值，如果是INSERT，就补充四个字段(创建时间、更新时间、创建人、更新人)
        try {
            if (operationType ==  OperationType.INSERT){
                //通过反射去补充创建时间和更新时间,操作人等属性值
                log.info("aop公共字段填充切面类开始进行数据填充,通过反射去补充创建时间和更新时间,操作人等属性值");
                Method setUpdateTime = object.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);//获取setUpdateTime方法,AutoFillConstant.SET_UPDATE_TIME等于"setUpdateTime"
                Method setCreateTime = object.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);//获取setCreateTime方法
                Method setCreateUser = object.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);//获取setCreateUser方法
                Method setUpdateUser = object.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);//获取setUpdateUser方法
                setCreateTime.invoke(object, LocalDateTime.now());//调用setCreateTime方法进行填充
                setUpdateTime.invoke(object, LocalDateTime.now());//调用setUpdateTime方法进行填充
                setCreateUser.invoke(object, BaseContext.getCurrentId());//调用setCreateUser方法进行填充
                setUpdateUser.invoke(object, BaseContext.getCurrentId());//调用setUpdateUser方法进行填充
                log.info("数据填充完成");
            }else if (operationType == OperationType.UPDATE){
                //4.判断注解中属性值，如果是UPDATE，就补充四个字段(更新时间、更新人)
                log.info("aop公共字段填充切面类开始进行数据填充,通过反射去补充更新时间,更新人属性值");
                Method setUpdateTime = object.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);//获取setUpdateTime方法
                Method setUpdateUser = object.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);//获取setUpdateUser方法
                setUpdateTime.invoke(object, LocalDateTime.now());//调用setUpdateTime方法进行填充
                setUpdateUser.invoke(object, BaseContext.getCurrentId());//调用setUpdateUser方法进行填充
                log.info("数据填充完成");
            }
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }

    }
}
